
/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2018原作者。
 *
 *根据Apache许可证2.0版（“许可证”）获得许可；
 *除非符合许可证，否则不得使用此文件。
 *您可以在以下地址获取许可证副本：
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，软件
 *根据许可证分发的内容是按“原样”分发的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限和
 *许可证下的限制。
 */

package org.springframework.beans.factory.config;

import java.beans.PropertyEditor;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;

/**
 * {@link BeanFactoryPostProcessor} implementation that allows for convenient
 * registration of custom {@link PropertyEditor property editors}.
 *
 * <p>In case you want to register {@link PropertyEditor} instances,
 * the recommended usage as of Spring 2.0 is to use custom
 * {@link PropertyEditorRegistrar} implementations that in turn register any
 * desired editor instances on a given
 * {@link org.springframework.beans.PropertyEditorRegistry registry}. Each
 * PropertyEditorRegistrar can register any number of custom editors.
 *
 * <pre class="code">
 * &lt;bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"&gt;
 *   &lt;property name="propertyEditorRegistrars"&gt;
 *     &lt;list&gt;
 *       &lt;bean class="mypackage.MyCustomDateEditorRegistrar"/&gt;
 *       &lt;bean class="mypackage.MyObjectEditorRegistrar"/&gt;
 *     &lt;/list&gt;
 *   &lt;/property&gt;
 * &lt;/bean&gt;
 * </pre>
 *
 * <p>
 * It's perfectly fine to register {@link PropertyEditor} <em>classes</em> via
 * the {@code customEditors} property. Spring will create fresh instances of
 * them for each editing attempt then:
 *
 * <pre class="code">
 * &lt;bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"&gt;
 *   &lt;property name="customEditors"&gt;
 *     &lt;map&gt;
 *       &lt;entry key="java.util.Date" value="mypackage.MyCustomDateEditor"/&gt;
 *       &lt;entry key="mypackage.MyObject" value="mypackage.MyObjectEditor"/&gt;
 *     &lt;/map&gt;
 *   &lt;/property&gt;
 * &lt;/bean&gt;
 * </pre>
 *
 * <p>
 * Note, that you shouldn't register {@link PropertyEditor} bean instances via
 * the {@code customEditors} property as {@link PropertyEditor PropertyEditors} are stateful
 * and the instances will then have to be synchronized for every editing
 * attempt. In case you need control over the instantiation process of
 * {@link PropertyEditor PropertyEditors}, use a {@link PropertyEditorRegistrar} to register
 * them.
 *
 * <p>
 * Also supports "java.lang.String[]"-style array class names and primitive
 * class names (e.g. "boolean"). Delegates to {@link ClassUtils} for actual
 * class name resolution.
 *
 * <p><b>NOTE:</b> Custom property editors registered with this configurer do
 * <i>not</i> apply to data binding. Custom editors for data binding need to
 * be registered on the {@link org.springframework.validation.DataBinder}:
 * Use a common base class or delegate to common PropertyEditorRegistrar
 * implementations to reuse editor registration there.
 *
 * @author Juergen Hoeller
 * @since 27.02.2004
 * @see java.beans.PropertyEditor
 * @see org.springframework.beans.PropertyEditorRegistrar
 * @see ConfigurableBeanFactory#addPropertyEditorRegistrar
 * @see ConfigurableBeanFactory#registerCustomEditor
 * @see org.springframework.validation.DataBinder#registerCustomEditor
 */
/**
 *｛@link BeanFactoryPostProcessor｝实现
 *注册自定义｛@link PropertyEditor属性编辑器｝。
 *
 *＜p＞如果要注册｛@link PropertyEditor｝实例，
 *从Spring 2.0开始，建议使用自定义
 *｛@link PropertyEditorRegistor｝实现，这些实现依次注册任何
 *所需的编辑器实例
 *｛@link org.springframework.beans.PropertyEditorRegistry注册表｝。每个
 *PropertyEditorRegister可以注册任意数量的自定义编辑器。
 *
 *<pre-class=“code”>
 *&lt；bean id=“customEditorConfigurer”class=“org.springframework.beans.factory.config.CustomEditorConfigureer”&gt；
 *&lt；property name=“propertyEditorRegisters”&gt；
 *&lt；列表&gt；
 *&lt；bean class=“mypackage.MyCustomDateEditorRegister”/&gt；
 *&lt；bean class=“mypackage.MyObjectEditorRegister”/&gt；
 *&lt/列表&gt；
 *&lt/属性&gt；
 *&lt/豆&gt；
 *</pre>
 *
 *＜p＞
 *通过
 *｛@code customEditors｝属性。Spring将创建
 *然后：
 *
 *<pre-class=“code”>
 *&lt；bean id=“customEditorConfigurer”class=“org.springframework.beans.factory.config.CustomEditorConfigureer”&gt；
 *&lt；property name=“customEditors”&gt；
 *&lt；地图&gt；
 *&lt；entry key=“java.util.Date”value=“mypackage.MyCustomDateEditor”/&gt；
 *&lt；entry key=“mypackage.MyObject”value=“mypackage.MyObjectEditor”/&gt；
 *&lt/地图&gt；
 *&lt/属性&gt；
 *&lt/豆&gt；
 *</pre>
 *
 *＜p＞
 *注意，您不应该通过
 *｛@code customEditors｝属性作为｛@link PropertyEditor PropertyEditors｝是有状态的
 *然后每次编辑都必须同步实例
 *尝试。如果您需要控制
 *｛@link PropertyEditor PropertyEditors｝，请使用｛@linkPropertyEditorRegister｝注册
 *他们。
 *
 *＜p＞
 *还支持“java.lang.String[]”样式的数组类名和原语
 *类名（例如“boolean”）。委托｛@link ClassUtils｝进行实际
 *类名解析。
 *
 *<p><b>注意：</b>使用此配置器注册的自定义属性编辑器
 *<i>不</i>适用于数据绑定。数据绑定的自定义编辑器需要
 *在｛@link org.springframework.validation.DataBinder｝上注册：
 *使用公共基类或委托给公共PropertyEditorRegister
 *实现重用编辑器注册。
 *
 *@作者Juergen Hoeller
 *@自2004年2月27日
 *@参见java.beans.PropertyEditor
 *@参见org.springframework.beans.PropertyEditorRegistor
 *@参见可配置的BeanFactory#addPropertyEditorRegistor
 *@参见可配置的BeanFactory#registerCustomEditor
 *@see org.springframework.validation.DataBinder#registerCustomEditor
 */
public class CustomEditorConfigurer implements BeanFactoryPostProcessor, Ordered {

	protected final Log logger = LogFactory.getLog(getClass());

	private int order = Ordered.LOWEST_PRECEDENCE;  // default: same as non-Ordered

	@Nullable
	private PropertyEditorRegistrar[] propertyEditorRegistrars;

	@Nullable
	private Map<Class<?>, Class<? extends PropertyEditor>> customEditors;


	public void setOrder(int order) {
		this.order = order;
	}

	@Override
	public int getOrder() {
		return this.order;
	}

	/**
	 * Specify the {@link PropertyEditorRegistrar PropertyEditorRegistrars}
	 * to apply to beans defined within the current application context.
	 * <p>This allows for sharing {@code PropertyEditorRegistrars} with
	 * {@link org.springframework.validation.DataBinder DataBinders}, etc.
	 * Furthermore, it avoids the need for synchronization on custom editors:
	 * A {@code PropertyEditorRegistrar} will always create fresh editor
	 * instances for each bean creation attempt.
	 * @see ConfigurableListableBeanFactory#addPropertyEditorRegistrar
	 */
	/**
	 *指定｛@link PropertyEditorRegistor PropertyEditorRegister｝
	 *应用于当前应用程序上下文中定义的bean。
	 *＜p＞这允许与共享｛@code PropertyEditorRegisters｝
	 *｛@link org.springframework.validation.DataBinder DataBinders｝等。
	 *此外，它还避免了在自定义编辑器上进行同步的需要：
	 *｛@code PropertyEditorRegister｝将始终创建新的编辑器
	 *每个bean创建尝试的实例。
	 *@see ConfigurationListableBeanFactory#addPropertyEditorRegister
	 */
	public void setPropertyEditorRegistrars(PropertyEditorRegistrar[] propertyEditorRegistrars) {
		this.propertyEditorRegistrars = propertyEditorRegistrars;
	}

	/**
	 * Specify the custom editors to register via a {@link Map}, using the
	 * class name of the required type as the key and the class name of the
	 * associated {@link PropertyEditor} as value.
	 * @see ConfigurableListableBeanFactory#registerCustomEditor
	 */
	/**
	 *使用
	 *所需类型的类名作为键
	 *关联｛@link PropertyEditor｝作为值。
	 *@see ConfigurationListableBeanFactory#registerCustomEditor
	 */
	public void setCustomEditors(Map<Class<?>, Class<? extends PropertyEditor>> customEditors) {
		this.customEditors = customEditors;
	}


	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		if (this.propertyEditorRegistrars != null) {
			for (PropertyEditorRegistrar propertyEditorRegistrar : this.propertyEditorRegistrars) {
				beanFactory.addPropertyEditorRegistrar(propertyEditorRegistrar);
			}
		}
		if (this.customEditors != null) {
			this.customEditors.forEach(beanFactory::registerCustomEditor);
		}
	}

}
